package me.wz.util.sdbc;

import me.wz.util.Assert;
import me.wz.util.exception.RTException;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * select * from T where x=:xxx => select * from T where x=?
 */
public class SQLParser {

    private String sql;
    private String[] names;
    private Object[] values;

    public SQLParser(String sql, Object params) throws IllegalAccessException { this.parse(sql, params); }

    private Object getVal(String key, Object params) throws IllegalAccessException {
        if( params != null ) {
            if(params instanceof Map) {
                Map<?,?> mp = (Map<?,?>) params;
                if( !mp.containsKey(key) ) {
                    throw new RTException("miss parameter :" + key);
                }
                return mp.get(key);
            }
            else {
                for(Field field : params.getClass().getDeclaredFields()) {
                    if( field.getName().equals(key) ) {
                        field.setAccessible(true);
                        return field.get(params);
                    }
                }
            }
        }
        throw new RTException("miss parameter :" + key);
    }
    private void parse(String sql, Object params) throws IllegalAccessException {
        Assert.hasText(sql, "sql can't null");

        List<String> strs = new ArrayList<String>();
        Pattern pattern = Pattern.compile(":(\\w+)");
        Matcher matcher = pattern.matcher(sql);
        while(matcher.find()){
            strs.add(matcher.group(1));
        }
        List<String> names = new ArrayList<String>();
        List<Object> values = new ArrayList<Object>();
        for(String str : strs) {
            Object val = getVal(str, params);
            if( val == null ) {
                //throw new RTException("miss parameter :" + str);
            }
            names.add(str);
            values.add(val);
        }
        this.sql = sql.replaceAll(":\\w+", "?");
        this.names = names.toArray(new String[]{});
        this.values = values.toArray(new Object[]{});
    }
    public String getSql(){ return this.sql; }
    public String[] getNames(){ return this.names; }
    public Object[] getValues(){ return this.values; }
}
